package com.treeroot.treenet.protocol.abs.tcp.session;

import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.channels.SelectionKey;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * Description: TCP 会话管理器，负责：
 * - 管理所有会话（TcpSession）
 * - 定期检查连接是否超时
 * - 超时则关闭并移除
 * Create By TreeRoot
 * Create Time: 2025/06/02 08:20
 * Class Name: TcpSessionManager
 *
 * @author TreeRoot
 */
public class TcpSessionManager {

    private static final Logger log = LoggerFactory.getLogger(TcpSessionManager.class);

    /**
     * 获取所有会话（用于外部访问）
     */
    @Getter
    private final Map<String, TcpSession> sessionMap = new ConcurrentHashMap<>();

    /**
     * 任务调度器，用于定时任务清除超时连接
     */
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    /**
     * 心跳超时时间（毫秒）
     */
    private final long heartbeatTimeoutMillis;
    /**
     * 心跳检测定时任务
     */
    private ScheduledFuture<?> heartbeatTask;

    /**
     * 构造函数 设置心跳超时时间
     *
     * @param heartbeatTimeoutMillis 毫秒
     */
    public TcpSessionManager(long heartbeatTimeoutMillis) {
        this.heartbeatTimeoutMillis = heartbeatTimeoutMillis;
    }

    /**
     * 添加会话
     */
    public void addSession(TcpSession session) {
        session.updateHeartbeat();
        sessionMap.put(session.getChannelId(), session);
        log.info("新连接加入会话管理器：{}", session.getChannelId());
    }

    /**
     * 移除会话
     */
    public void removeSession(String channelId) {
        TcpSession session = sessionMap.remove(channelId);
        if (session != null) {
            try {
                session.getClientChannel().close();
                log.info("连接已关闭并移除：{}", channelId);
                log.info("【===================通道{}连接请求结束===================】", channelId);
            } catch (Exception e) {
                log.warn("关闭连接异常：{}", channelId, e);
            }
        }
    }

    /**
     * 启动定时任务，定期检测超时连接
     */
    public void start() {
        heartbeatTask = scheduler.scheduleAtFixedRate(() -> {
            long now = System.currentTimeMillis();
            for (Map.Entry<String, TcpSession> entry : sessionMap.entrySet()) {
                TcpSession session = entry.getValue();
                if (now - session.getLastHeartbeatTime() > heartbeatTimeoutMillis) {
                    log.warn("连接超时，踢出并关闭：{}", entry.getKey());
                    removeSession(entry.getKey());
                }
            }
            // 每 10 秒检查一次
        }, 10, 10, TimeUnit.SECONDS);
    }

    /**
     * 按键查找会话
     *
     * @param key key
     * @return {@link TcpSession }
     */
    public TcpSession findSessionByKey(SelectionKey key) {
        for (TcpSession session : sessionMap.values()) {
            if (session.getKey().equals(key)) {
                return session;
            }
        }
        return null;
    }

    /**
     * 停止心跳检测任务并清理连接
     */
    public void stop() {
        if (heartbeatTask != null) {
            heartbeatTask.cancel(true);
        }
        scheduler.shutdown();
        for (String channelId : sessionMap.keySet()) {
            removeSession(channelId);
        }
        log.info("TCP 会话管理器已停止");
    }

}